"""
@Author：WangYuXiang
@E-mile：Hill@3io.cc
@CreateTime：2021/3/24 16:35
@DependencyLibrary：无
@MainFunction：无
@FileDoc： 
    models.py
    文件说明
@ChangeHistory:
    datetime action why
    example:
    2021/3/24 16:35 change 'Fix bug'
        
"""

import hashlib
from typing import List

from tortoise import fields

from common.utils.models import BaseModel


class UserModel(BaseModel):
    """用户/人员表"""
    nickname = fields.CharField(32, null=True, description='昵称', unique=True)
    account = fields.CharField(18, description='账号', unique=True)
    pwd = fields.CharField(128, description='密码')
    phone = fields.CharField(11, null=True, description='手机号')
    wx = fields.CharField(32, null=True, description='微信账号')
    login_datetime = fields.DatetimeField(auto_now=True, description='登录时间')
    last_login_datetime = fields.DatetimeField(auto_now_add=True, description='上次登录时间')
    is_active = fields.BooleanField(description="状态", default=True)
    is_super_admin = fields.BooleanField(description="是否是超级管理员", default=True)
    now_role_id = fields.IntField(null=True, description='当前选中的角色ID')
    is_staff = fields.BooleanField(default=False, description='是否是员工')

    roles: fields.ManyToManyRelation["RoleModel"] = fields.ManyToManyField('auth.RoleModel', through='role2user',
                                                                           related_name='users', null=True)

    @classmethod
    def encryption_password(cls, pwd: str):
        """加密密码"""
        return hashlib.md5(pwd.encode('utf8')).hexdigest()

    def set_password(self, pwd: str):
        """设置加密的密码"""
        self.pwd = UserModel.encryption_password(pwd)

    def check_password(self, pwd: str):
        """检查密码"""
        if pwd is None:
            return False
        return self.pwd == UserModel.encryption_password(pwd)

    async def permissions(self, is_inherit=True, now_role=True) -> List['PermissionModel']:
        """
        用户的权限对象
        :param is_inherit: 是否继承组织机构 权限
        :param now_role: 是只查已选中角色的权限
        :return:
        """
        return await self._permissions(is_inherit, now_role)

    async def permissions_code(self, is_inherit=True, now_role=True) -> List[str]:
        """
        用户的权限代码
        :param is_inherit: 是否继承组织机构 权限
        :param now_role: 是只查已选中角色的权限
        :return:
        """
        permissions = await self.permissions(is_inherit, now_role)
        return [i.code for i in permissions]

    async def _permissions(self, is_inherit=True, now_role=True) -> List['PermissionModel']:
        """
        用户的权限对象
        :param is_inherit: 是否继承组织机构 权限
        :param now_role: 是只查已选中角色的权限
        :return:
        """
        perms = []
        if self.is_super_admin:
            return await PermissionModel.all()

        if now_role:
            roles = await self.roles.filter(id=self.now_role_id).all()
        else:
            roles = await self.roles.all()

        for role in roles:
            role_perms = await role.all_permissions(is_inherit)
            perms.extend(role_perms)
        return perms

    async def has_permissions(self, code, is_inherit=True, now_role=True) -> bool:
        """
        是否拥有某项权限
        :param code: 权限代码 list or str
        :param is_inherit: 是否继承查询false查role ，true 查询role group
        :param now_role:  是否只查 self.now_role_id 角色的权限
        :return: 
        """
        permission_code_list = await self.permissions_code(is_inherit, now_role)
        if isinstance(code, list):
            return all([permission in permission_code_list for permission in code])
        return code in permission_code_list


class GroupModel(BaseModel):
    """用户分组/组织架构表"""
    name = fields.CharField(128, description='组名')
    code = fields.CharField(512, unique=True, description='组代码')
    parent = fields.ForeignKeyField('auth.GroupModel', related_name='child', null=True)
    permissions: fields.ManyToManyRelation["PermissionModel"] = fields.ManyToManyField('auth.PermissionModel',
                                                                                       through='group2perm',
                                                                                       related_name='groups', null=True)

    roles: fields.ReverseRelation["RoleModel"]

    async def all_permissions(self, is_inherit=True) -> list:
        """得到组织机构的所有权限对象"""
        if not is_inherit:
            permission_code_list = await self.permissions.all()
            return permission_code_list
        return await self._recursive_parent_group_permissions(self)

    async def _recursive_parent_group_permissions(self, group) -> list:
        """递归得到父级组织机构权限"""
        perms = []
        parent = await group.parent
        if parent:
            perms = await self._recursive_parent_group_permissions(parent)
        permission_code_list = await group.permissions.all()
        perms.extend(permission_code_list)
        return perms


class RoleModel(BaseModel):
    """角色/岗位表"""
    name = fields.CharField(128, description='角色名')
    code = fields.CharField(512, unique=True, description='角色代码')
    group: fields.ForeignKeyRelation[GroupModel] = fields.ForeignKeyField(model_name='auth.GroupModel', related_name='roles', null=True)
    permissions: fields.ManyToManyRelation["PermissionModel"] = fields.ManyToManyField(model_name='auth.PermissionModel',
                                                                                       through='role2perm',
                                                                                       related_name='roles', null=True)
    users: fields.ManyToManyRelation[UserModel]

    async def all_permissions(self, is_inherit=True) -> list:
        """得到角色/岗位的所有权限对象"""
        perms = await self.permissions.all()
        if not is_inherit:
            return perms

        group = await self.group
        group_perms = await group.all_permissions(is_inherit)
        perms.extend(group_perms)
        return perms


class PermissionModel(BaseModel):
    """权限代码表"""
    name = fields.CharField(128, description='权限名')
    code = fields.CharField(512, unique=True, description='权限代码', pk=True)
    classify_code = fields.CharField(128, null=False)
    classify_name = fields.CharField(128, null=True)
    roles: fields.ManyToManyRelation[RoleModel]
    groups: fields.ManyToManyRelation[GroupModel]
